
// FillDiskPublic.cpp : Defines the class behaviors for the application.
//

/*
*****************************************************************************
*                                                                           *
*   Program functions:                                                      *
*                                                                           *
*   Fill hard disk(s) by dummy files                                        *
*                                                                           *
*   Author: Allan Qiu                                                       *
*                                                                           *
*   Version: 1.1.0.1                                                        *
*                                                                           *
*   Latest update: 2012-06-17 by Allan Qiu                                  *
*                                                                           *
*****************************************************************************
*/

#include "stdafx.h"
#include "FillDiskPublic.h"
#include "FillDiskPublicDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CFillDiskPublicApp

BEGIN_MESSAGE_MAP(CFillDiskPublicApp, CWinApp)
	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// CFillDiskPublicApp construction

CFillDiskPublicApp::CFillDiskPublicApp()
{
	// support Restart Manager
	m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;

}


// The one and only CFillDiskPublicApp object

CFillDiskPublicApp theApp;


// CFillDiskPublicApp initialization

BOOL CFillDiskPublicApp::InitInstance()
{
	// InitCommonControlsEx() is required on Windows XP if an application
	// manifest specifies use of ComCtl32.dll version 6 or later to enable
	// visual styles.  Otherwise, any window creation will fail.
	INITCOMMONCONTROLSEX InitCtrls;
	InitCtrls.dwSize = sizeof(InitCtrls);
	// Set this to include all the common control classes you want to use
	// in your application.
	InitCtrls.dwICC = ICC_WIN95_CLASSES;
	InitCommonControlsEx(&InitCtrls);

	CWinApp::InitInstance();


	AfxEnableControlContainer();

	// Create the shell manager, in case the dialog contains
	// any shell tree view or shell list view controls.
	CShellManager *pShellManager = new CShellManager;

	// Standard initialization
	// If you are not using these features and wish to reduce the size
	// of your final executable, you should remove from the following
	// the specific initialization routines you do not need
	// Change the registry key under which our settings are stored
	// TODO: You should modify this string to be something appropriate
	// such as the name of your company or organization
	SetRegistryKey(_T("Local AppWizard-Generated Applications"));

	CFillDiskPublicDlg dlg;
	switch(CheckCmdParams())
	{
	case CA_HelpArg:
		//Help: Show help window, then exit.
		dlg.ShowHelpWindow();
		return FALSE;
		break;
	case CA_ErrorArgs:
		//Error: Show error message, then run to main window.
		dlg.SetStartWithCmdArgs(false);
		dlg.ShowErrorWindow();
		break;
	case CA_CleanArg:
		// Clean: Delete existed dummy files.
		dlg.SetStartWithCmdArgs(true);
		AllocConsole();
		dlg.SetOutPutCmdHandle(GetStdHandle(STD_OUTPUT_HANDLE));
		dlg.DeleteAllFillFiles();
		dlg.SetOutPutCmdHandle(NULL);
		FreeConsole();
		return FALSE;
		break;
	case CA_FillAllDisksArg:
		// Fill all disks by dummy files.
		dlg.SetStartWithCmdArgs(true);
		AllocConsole();
		dlg.SetOutPutCmdHandle(GetStdHandle(STD_OUTPUT_HANDLE));
		dlg.FillAllDiskSpace(_wtoi64(m_strArgsList.GetAt(m_strArgsList.FindIndex(3))));
		dlg.AfterAllDiskFillFinished();
		dlg.SetOutPutCmdHandle(NULL);
		FreeConsole();
		return FALSE;
		break;
	case CA_FillSomeDisksArg:
		// Fill specified disks by dummy files.
		dlg.SetStartWithCmdArgs(true);
		AllocConsole();
		dlg.SetOutPutCmdHandle(GetStdHandle(STD_OUTPUT_HANDLE));
		for (int i = 2; i < m_strArgsList.GetCount() - 1; i++)
		{
			wchar_t wchDriveLetter[4] = _T(" :\\");
			wchDriveLetter[0] = m_strArgsList.GetAt(m_strArgsList.FindIndex(i))[0];
			dlg.FillOneDiskSpace(wchDriveLetter, 
				_wtoi64(m_strArgsList.GetAt(m_strArgsList.
				FindIndex(m_strArgsList.GetCount() - 1))));
		}
		dlg.AfterAllDiskFillFinished();
		dlg.SetOutPutCmdHandle(NULL);
		FreeConsole();
		return FALSE;
		break;
	case CA_NoArgs:
	default:
		dlg.SetStartWithCmdArgs(false);
		break;
	}

	m_pMainWnd = &dlg;
	INT_PTR nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// Exit.
	}
	else if (nResponse == IDCANCEL)
	{
		// Exit.
	}
	else if (nResponse == -1)
	{
		TRACE(traceAppMsg, 0, "Warning: dialog creation failed, so application is terminating unexpectedly.\n");
		TRACE(traceAppMsg, 0, "Warning: if you are using MFC controls on the dialog, you cannot #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS.\n");
	}

	// Delete the shell manager created above.
	if (pShellManager != NULL)
	{
		delete pShellManager;
	}

	// Since the dialog has been closed, return FALSE so that we exit the
	//  application, rather than start the application's message pump.
	return FALSE;
}

enum CFillDiskPublicApp::enumCmdArgs CFillDiskPublicApp::CheckCmdParams()
{
	m_strArgsList.RemoveAll();

	LPWSTR * szArgsList;
	int nArgs;
	szArgsList = CommandLineToArgvW(GetCommandLine(), &nArgs);

	// Cannot get arguments
	if (NULL == szArgsList)
	{
		return CA_ErrorArgs;
	}

	//	Only execute file name, no arguments
	if (1 == nArgs)
	{
		return CA_NoArgs;
	}

	// Import the arguments into CList<CString, CString&> m_strArgsList
	// Include the execute file name, so the "count of list" = "args count" + 1
	for (int i = 0; i < nArgs; i++)
	{
		m_strArgsList.AddTail(CString(szArgsList[i]).MakeLower());
	}

	LocalFree(szArgsList);

	if (TRUE == IsHelpArg())
		return CA_HelpArg;

	if (TRUE == IsCleanArg())
		return CA_CleanArg;

	if (TRUE == IsFillAllDisk())
		return CA_FillAllDisksArg;

	if (TRUE == IsFillSomeDisk())
		return CA_FillSomeDisksArg;

	return CA_ErrorArgs;
}

BOOL CFillDiskPublicApp::IsHelpArg()
{
	// Help arg: -?, /? , -h, /h, -help, /help
	// When arguments include "Help" arg, ignore other args.

	CString strArg;
	for (int i = 1; i < m_strArgsList.GetCount(); i++)
	{
		strArg = m_strArgsList.GetAt(m_strArgsList.FindIndex(i));
		if (   ((CString)"-?"    == strArg) || ((CString)"/?"    == strArg)
			|| ((CString)"-h"    == strArg) || ((CString)"/h"    == strArg)
			|| ((CString)"-help" == strArg) || ((CString)"/help" == strArg))
		{
			return TRUE;
		}
	}

	return FALSE;
}

BOOL CFillDiskPublicApp::IsCleanArg()
{
	// Clean arg: -clean
	CString strArg = m_strArgsList.GetAt(m_strArgsList.FindIndex(1));
	if (((CString)"/clean" == strArg) || ((CString)"-clean" == strArg))
	{
		// Please keep clean arg alone, otherwise means error args.
		if (2 == m_strArgsList.GetCount())
		{
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
	return FALSE;
}

BOOL CFillDiskPublicApp::IsFillDisk()
{
	CString strArg = m_strArgsList.GetAt(m_strArgsList.FindIndex(1));

	// Fill arg: -fill
	if (((CString)"/fill" == strArg) || ((CString)"-fill" == strArg))
	{
		int n = m_strArgsList.GetCount();
		// The minimum number for fill arg is 3: "filldisk.exe /fill all 10"
		if (n < 4)
		{
			return FALSE;
		}

		// The last fill arg must be a "number", and greater than 0.
		CString strTemp = m_strArgsList.GetAt(m_strArgsList.FindIndex(n - 1));
		for (int i = 0; i < strTemp.GetLength(); i++)
		{
			if (0 == isdigit(strTemp[i]))
			{
				return FALSE;
			}
		}
		
		if ( _wtoi64(strTemp.Trim()) <= 0)
		{
			return FALSE;
		}

		return TRUE;
	}

	return FALSE;
}

BOOL CFillDiskPublicApp::IsFillAllDisk()
{
	if (FALSE == IsFillDisk())
	{
		return FALSE;
	}

	// Only 3 args for fill all disk: "filldisk.exe /fill all 10".
	if ((CString)"all" == m_strArgsList.GetAt(m_strArgsList.FindIndex(2)))
	{
		if (4 < m_strArgsList.GetCount())
		{
			return FALSE;
		}
		else
		{
			return TRUE;
		}
	}

	return FALSE;
}

BOOL CFillDiskPublicApp::IsFillSomeDisk()
{
	if (FALSE == IsFillDisk())
	{
		return FALSE;
	}

	// Fill some disks: "filldisk.exe /fill c e 10"
	for (int i = 2; i < m_strArgsList.GetCount() - 1; i++)
	{
		CString strTemp = m_strArgsList.GetAt(m_strArgsList.FindIndex(i));
		if (1 != strTemp.GetLength())
		{
			return FALSE;
		}

		if ((strTemp < (CString)"a") || ((CString)"z" < strTemp))
		{
			return FALSE;
		}
	}

	return TRUE;
}
